package com.spring;

import com.spring.beans.factory.anno.Autowired;
import com.spring.anno.Component;
import com.spring.anno.ComponentScan;
import com.spring.anno.scope;
import com.spring.interfaces.BeanNameAware;
import com.spring.interfaces.BeanPostProcessor;
import com.spring.interfaces.InitializingBean;

import java.beans.Introspector;
import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Author: Asuka
 * @Description:
 * @create: 2025-04-05 01:20
 */


public class ApplicationContextOld {

    private Class configClass;

    //单例池
    private ConcurrentHashMap<String,Object> singletonHashMap = new ConcurrentHashMap<>();
    //bean定义池
    private ConcurrentHashMap<String,BeanDefinition> beanDefinitionHashMap = new ConcurrentHashMap<>();
    //BeanPostProcessor 集合
    //TreeMap<Integer,BeanPostProcessor> beanPostProcessorList = new TreeMap<>();
    List<BeanPostProcessor> beanPostProcessorList = new ArrayList<>();


    public ApplicationContextOld(Class configClass){
        this.configClass = configClass;

        //扫描 获取bean 并添加到 单例池 和 bean定义池
        scanf(configClass);

        //依赖注入
        /*beanDefinitionHashMap.forEach((beanName,beanDefinition)->{

            Class clazz = beanDefinition.getclazz();

            //为方法所有成员变量注入
            for (Field field : clazz.getDeclaredFields()) {
                if(!field.isAnnotationPresent(Autowired.class)){
                    continue;
                }

                field.setAccessible(true);
                Class<?> type = field.getType();
                String value = type.getAnnotation(Component.class).value();
                try {
                    field.set(clazz,getBean(value));
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }

            }
        });*/

    }

    private void scanf(Class configClass) {
        //解析
        ComponentScan componentScan = (ComponentScan) configClass.getDeclaredAnnotation(ComponentScan.class);
        //获取扫描路径
        String path = componentScan.value();
        path = path.replace(".","/");


        //扫描
        ClassLoader classLoader = ApplicationContextOld.class.getClassLoader();

        URL resource = classLoader.getResource(path);


        // /D:/JavaProect/spring/minispring/target/classes/com/sumika/service
        //去除开头的 /
        String filePath = resource.getFile();
        if(filePath.startsWith("/")){
            filePath = filePath.substring(1);
        }

        //获取路径下的文件
        File file = new File(filePath);
        if(file.isDirectory()){
            File[] files = file.listFiles();
            for (File f : files) {
                String fileName = f.getAbsolutePath();

                if(!fileName.endsWith(".class")){
                    continue;
                }

                String className = fileName.substring(fileName.indexOf("com"),fileName.indexOf(".class"));
                className = className.replace("\\",".");

                try {
                    Class<?> clazz = classLoader.loadClass(className);
                    if (clazz.isAnnotationPresent(Component.class)){

                        //获取bean的名字
                        String beanName = getBeanName(clazz);

                        BeanDefinition beanDefinition = new BeanDefinition();
                        //判断是否单例
                        if(clazz.isAnnotationPresent(scope.class)){
                            scope scopeAnnotation = clazz.getDeclaredAnnotation(scope.class);
                            beanDefinition.setScope(scopeAnnotation.value());
                        }else{
                            beanDefinition.setScope(Constant.SINGLETON);
                        }
                        beanDefinition.setBeanClass(clazz);
                        beanDefinitionHashMap.put(beanName,beanDefinition);

                    }
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                }

            }
        }


        //将定义bean池里单例的创建到单例池里
        beanDefinitionHashMap.forEach((beanName,beanDefinition)-> {
            if (beanDefinition.getScope().equals(Constant.SINGLETON)){
                Object bean = createBean(beanDefinition);
                singletonHashMap.put(beanName,bean);
            }
        });
    }

    private static String getBeanName(Class<?> clazz) {
        Component componentAnnotation = clazz.getDeclaredAnnotation(Component.class);
        String beanName = componentAnnotation.value();

        if(beanName.equals("")){
            //类短名首字母小写
            beanName = Introspector.decapitalize(clazz.getSimpleName());
        }

        return beanName;
    }


    public Object createBean(BeanDefinition beanDefinition){
        Class clazz = beanDefinition.getBeanClass();

        //通过反射创建对应bean对象
        try {

            //是否实现了BeanPostProcessor
            if (BeanPostProcessor.class.isAssignableFrom(clazz)) {
                //类上有排序注解就获取排序值, 没有就默认5

                BeanPostProcessor beanPostProcessorInstance = (BeanPostProcessor) clazz.getDeclaredConstructor().newInstance();
                beanPostProcessorList.add(beanPostProcessorInstance);
            }

            Object instance = clazz.getDeclaredConstructor().newInstance();

            //依赖注入
            for (Field field : instance.getClass().getDeclaredFields()) {
                if (!field.isAnnotationPresent(Autowired.class)) {
                    continue;
                }

                Class<?> type = field.getType();
                String beanName = getBeanName(type);
                field.setAccessible(true);
                Object bean = getBean(beanName);

                field.set(instance,bean);
                instance.getClass().getMethod("sout").invoke(instance);
            }


            String beanName = getBeanName(instance.getClass());

            // Aware回调 设置beanName
            if(instance instanceof BeanNameAware){
                ((BeanNameAware)(instance)).setBeanName(beanName);
            }


            //BeanPostprocessor 初始化前调用
            for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
                instance = beanPostProcessor.postProcessBeforeInitialization(beanName,instance);
            }

            //初始化
            if(instance instanceof InitializingBean){
                try {
                    ((InitializingBean)(instance)).afterPropertiesSet();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }


            //BeanPostprocessor 初始化后调用
            for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
                instance = beanPostProcessor.postProcessAfterInitialization(beanName,instance);
            }


            return instance;
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }

        return null;
    }


    public Object getBean(String beanName){

        //判断是否存在
        if(!beanDefinitionHashMap.containsKey(beanName)){
            throw new NullPointerException();
        }


        BeanDefinition beanDefinition = beanDefinitionHashMap.get(beanName);
        //判断是否单例
        if (beanDefinition.getScope().equals(Constant.SINGLETON)) {
            return singletonHashMap.get(beanName);
        }

        return createBean(beanDefinition);
    }



}
